import * as THREE from 'three'
import Scene from './scene'
import createBuilding from './geometryModel'
import createWallByPath from './wallByPath.js'
import createWallMaterial from './wallMaterial.js'
import { cityData, roadData } from './cityData'
import flyCurve from './flyCurve'
import {
  createNewPolygon,
  pointListToV3,
  getFlyCurve,
  generatePoints
} from './utils'

export default class City {
  elName!: string
  scene!: Scene
  buildingObjects: THREE.Mesh[] = []
  buildingObjectName: string = 'building'
  wallObjects: THREE.Mesh[] = []
  textureObjects: THREE.Texture[] = []
  lineTexture!: THREE.Texture
  raycaster = new THREE.Raycaster()
  mouse = new THREE.Vector2()
  textureLoader = new THREE.TextureLoader()
  

  constructor(elName: string) {
    this.elName = elName
    this.init()
  }

  init() {
    this.scene = new Scene(this.elName, this.update.bind(this))
    for (let i = 0; i < cityData.length; i++) {
      this.initWall(cityData[i].points, cityData[i].height)
      this.initBuilding(cityData[i].points, cityData[i].height)
    }
    this.initFlyCurve()
    // this.initBuildingLine()
    window.addEventListener('mousemove', this.onMouseMove.bind(this), false);
  }

  update() {
    // flyCurve.timerFlyCurve()
    if (this.textureObjects.length) {
      this.textureObjects.forEach((texture) => {
        if (texture) texture.offset.x -= 0.01
      })
    }
    if (this.wallObjects.length) {
      this.wallObjects.forEach((obj: any) => {
        obj.material.uniforms.time.value += 0.01
      })
    }
  }

  onMouseMove(event: MouseEvent): void {
    // 将鼠标点击位置的屏幕坐标转换为WebGL的标准设备坐标
    this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    // 通过摄像机和鼠标位置更新射线
    this.raycaster.setFromCamera(this.mouse, this.scene.camera);
    for (let i = 0; i < this.buildingObjects.length; i++) {
      (this.buildingObjects[i].material as any).color = new THREE.Color(0x002037)
      document.body.style.cursor = "auto"
    }
    // 计算物体和射线的焦点
    const intersects = this.raycaster.intersectObjects(this.buildingObjects);
    for (let i = 0; i < intersects.length; i++) {
      const object = intersects[i].object
      if (object.name === this.buildingObjectName && object instanceof THREE.Mesh) {
        document.body.style.cursor = "pointer"
        object.material.color = new THREE.Color(0x0F716F)
        break
      }
    }
  }

  /**绘制楼体 */
  initBuilding(points: [number, number][], height: number) {
    const geometryModel = createBuilding({
      points,
      color: new THREE.Color(0x002037),
      height,
      name: this.buildingObjectName
    })
    this.scene.scene.add(geometryModel)
    this.buildingObjects.push(geometryModel)
  }

  /**绘制光圈 */
  initWall(points: [number, number][], height: number) {
    const wallPoints = createNewPolygon(points, 0.5)
    const bgTexture = this.textureLoader.load('images/1.png')
    const flowTexture = this.textureLoader.load('images/2.png')
    const material = createWallMaterial({
      bgTexture,
      flowTexture
    })

    let linePoints = pointListToV3(wallPoints, true)
    const wallMesh = createWallByPath({
      height: height * 2,
      path: linePoints,
      material,
      expand: true
    })
    this.scene.scene.add(wallMesh)
    this.wallObjects.push(wallMesh)
  }

  /**绘制建筑外墙线圈 */
  initBuildingLine() {
    const points = cityData[0].points
    const wallPoints = createNewPolygon(points, 0.5)
    const pointsV3 = pointListToV3(points, false, 5)
    const flyLine = flyCurve.createFlyCurve(pointsV3, true)
    this.scene.scene.add(flyLine)
  }

  /**绘制流光 */
  initFlyCurve() {
    // const linePoints: [number, number][] = [
    //   [12, 50], [12, 0], [12, -50]
    // ]
    // const pointsV3 = pointListToV3(linePoints)
    // const flyLine = flyCurve.createFlyCurve(pointsV3, false)
    // this.scene.scene.add(flyLine)
    // 贴图类型
    for (let i = 0; i < roadData.length; i++) {
      const curve = getFlyCurve({
        points: roadData[i].points,
        size: roadData[i].size,
        repeatX: roadData[i].repeatX || 3
      })
      this.scene.scene.add(curve.lineMesh)
      this.textureObjects.push(curve.lineTexture)
    }
  }
}